<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Pipeline_Synchronizer_Lazy.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Takes in two or more pipelines and synchronizes them so they can only complete their handshakes simultaneously, then outputs the synchronized handshakes. This forces data to be consumed in FIFO order and in lock-step for all pipelines (e.g.: addresses and data for a memory write, each from independent sources).">
<title>Pipeline Synchronizer Lazy</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Pipeline_Synchronizer_Lazy.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Pipeline Synchronizer (Lazy)</h1>
<p>Takes in two or more pipelines and synchronizes them so they can only
 complete their handshakes simultaneously, then outputs the synchronized
 handshakes. This forces data to be consumed in FIFO order and in lock-step
 for all pipelines (e.g.: addresses and data for a memory write, each from
 independent sources).</p>
<p>We synchronize by first Joining the pipelines, then re-forking them and
 discarding all but one copy of the data.</p>
<p>A consequence of the synchronization is that the ready signal of the input
 interfaces will only assert once <em>all</em> input valid lines are asserted. This
 is a combinational path. There is no buffering. Watch out for combinational
 loops.</p>
<h2>Ports, Parameters, and Constants</h2>

<pre>
`default_nettype none

module <a href="./Pipeline_Synchronizer_Lazy.html">Pipeline_Synchronizer_Lazy</a>
#(
    parameter WORD_WIDTH        = 0,
    parameter PORT_COUNT        = 0,

    // Do not set at instantiation, except in Vivado IPI
    parameter PORT_WIDTH_TOTAL  = WORD_WIDTH * PORT_COUNT
)
(
    output  wire    [PORT_COUNT-1:0]        input_data_ready,
    input   wire    [PORT_COUNT-1:0]        input_data_valid,
    input   wire    [PORT_WIDTH_TOTAL-1:0]  input_data,

    input   wire    [PORT_COUNT-1:0]        output_data_ready,
    output  wire    [PORT_COUNT-1:0]        output_data_valid,
    output  reg     [PORT_WIDTH_TOTAL-1:0]  output_data
);

    localparam PORT_WIDTH_TOTAL_ZERO = {PORT_WIDTH_TOTAL{1'b0}};

    initial begin
        output_data = PORT_WIDTH_TOTAL_ZERO;
    end
</pre>

<h2>Input Join</h2>

<pre>
    wire                        input_data_joined_valid;
    wire                        input_data_joined_ready;
    wire [PORT_WIDTH_TOTAL-1:0] input_data_joined;

    <a href="./Pipeline_Join_Lazy.html">Pipeline_Join_Lazy</a>
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .INPUT_COUNT    (PORT_COUNT)
    )
    input_join
    (
        .input_valid    (input_data_valid),
        .input_ready    (input_data_ready),
        .input_data     (input_data),

        .output_valid   (input_data_joined_valid),
        .output_ready   (input_data_joined_ready),
        .output_data    (input_data_joined)
    );
</pre>

<h2>Output Fork</h2>
<p>We end up with duplicates of the input data since we are creating
 <code>PORT_COUNT</code> forked copies of all the <code>PORT_COUNT</code> input data interfaces
 joined together. So we discard all but the first copy and keep all the
 control signals.</p>

<pre>
    localparam PORT_WIDTH_TOTAL_WITH_DUPLICATES = PORT_WIDTH_TOTAL * PORT_COUNT;

    // verilator lint_off UNUSED
    wire [PORT_WIDTH_TOTAL_WITH_DUPLICATES-1:0] output_data_with_duplicates;
    // verilator lint_on  UNUSED

    <a href="./Pipeline_Fork_Lazy.html">Pipeline_Fork_Lazy</a>
    #(
        .WORD_WIDTH     (PORT_WIDTH_TOTAL),
        .OUTPUT_COUNT   (PORT_COUNT)
    )
    output_fork
    (
        .input_valid    (input_data_joined_valid),
        .input_ready    (input_data_joined_ready),
        .input_data     (input_data_joined),

        .output_valid   (output_data_valid),
        .output_ready   (output_data_ready),
        .output_data    (output_data_with_duplicates)
    );

    always @(*) begin
        output_data = output_data_with_duplicates [0 +: PORT_WIDTH_TOTAL];
    end

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

